# coding=utf-8
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import threading
import csv
import json
import os
from torrent_scraper import run as fetch_torrents, get_rules

class TorrentSearchApp:
    def __init__(self, root):
        self.root = root
        self.root.title("多站点种子搜索工具 v3.0")
        self.root.geometry("1366x768")

        self.rules = get_rules()
        if not self.rules:
            messagebox.showerror("错误", "未在 'rules' 目录中找到任何有效的规则文件。程序无法启动。")
            root.destroy()
            return

        self.current_page = 1
        self.total_pages = 1
        self.last_search_keywords = []
        self.current_rule = tk.StringVar(value=self.rules[0]['name'])

        style = ttk.Style()
        style.theme_use('clam')
        style.configure("TLabel", font=("微软雅黑", 10))
        style.configure("TButton", font=("微软雅黑", 10), padding=5)
        style.configure("TCheckbutton", font=("微软雅黑", 10))
        style.configure("TRadiobutton", font=("微软雅黑", 10))
        style.configure("TEntry", font=("微软雅黑", 10), padding=5)
        style.configure("Treeview.Heading", font=("微软雅黑", 10, "bold"))
        style.configure("TLabelframe.Label", font=("微软雅黑", 11, "bold"))

        main_frame = ttk.Frame(root, padding="10")
        main_frame.pack(fill=tk.BOTH, expand=True)
        main_frame.columnconfigure(0, weight=1)
        main_frame.rowconfigure(1, weight=1)

        controls_frame = ttk.LabelFrame(main_frame, text="搜索条件", padding="10")
        controls_frame.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
        self.create_search_controls(controls_frame)

        results_frame = ttk.LabelFrame(main_frame, text="搜索结果", padding="10")
        results_frame.grid(row=1, column=0, sticky="nsew", padx=5, pady=5)
        results_frame.columnconfigure(0, weight=1)
        results_frame.rowconfigure(0, weight=1)
        self.create_results_view(results_frame)

        actions_frame = ttk.Frame(main_frame)
        actions_frame.grid(row=2, column=0, sticky="ew", padx=5, pady=5)
        actions_frame.columnconfigure(1, weight=1)
        self.create_action_buttons(actions_frame)
        self.create_pagination_controls(actions_frame)

        self.status_var = tk.StringVar(value="准备就绪")
        self.status_bar = ttk.Label(main_frame, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W, padding=5)
        self.status_bar.grid(row=3, column=0, sticky="ew", padx=5, pady=5)

    def create_search_controls(self, parent):
        parent.columnconfigure(1, weight=1)
        
        ttk.Label(parent, text="搜索引擎:").grid(row=0, column=0, sticky="w", padx=5, pady=5)
        source_menu = ttk.OptionMenu(parent, self.current_rule, self.rules[0]['name'], *[r['name'] for r in self.rules])
        source_menu.grid(row=0, column=1, sticky="w", padx=5, pady=5)

        ttk.Label(parent, text="关键词:").grid(row=0, column=2, sticky="w", padx=5, pady=5)
        self.keyword_var = tk.StringVar(value="school")
        self.keyword_entry = ttk.Entry(parent, textvariable=self.keyword_var)
        self.keyword_entry.grid(row=0, column=3, columnspan=2, sticky="ew", padx=5, pady=5)

        preset_frame = ttk.LabelFrame(parent, text="预设关键词 (可多选)", padding="5")
        preset_frame.grid(row=1, column=0, columnspan=5, sticky="ew", padx=5, pady=5)
        self.preset_vars = {}
        preset_keywords = ["japan leak", "japan database", "japanese leak", "japan data breach", "japan dump", "日本 漏洩", "日本 データ漏洩", "jp leak", "jp database", "jp combo list"]
        for i, keyword in enumerate(preset_keywords):
            var = tk.BooleanVar()
            cb = ttk.Checkbutton(preset_frame, text=keyword, variable=var)
            cb.grid(row=i // 5, column=i % 5, sticky="w", padx=5, pady=2)
            self.preset_vars[keyword] = var

        ext_frame = ttk.LabelFrame(parent, text="文件后缀 (可多选)", padding="5")
        ext_frame.grid(row=2, column=0, columnspan=5, sticky="ew", padx=5, pady=5)
        self.ext_vars = {}
        extensions = [".txt", ".csv", ".7z", ".rar", ".zip"]
        for i, ext in enumerate(extensions):
            var = tk.BooleanVar()
            cb = ttk.Checkbutton(ext_frame, text=ext, variable=var)
            cb.grid(row=0, column=i, sticky="w", padx=5, pady=2)
            self.ext_vars[ext] = var

        options_frame = ttk.Frame(parent)
        options_frame.grid(row=3, column=0, columnspan=5, sticky="ew", padx=5, pady=10)
        options_frame.columnconfigure(2, weight=1)

        ttk.Label(options_frame, text="排序方式:").pack(side=tk.LEFT, padx=(0, 5))
        self.sort_var = tk.StringVar(value='date')
        sort_options = [("日期", 'date'), ("大小", 'size'), ("热度", 'peers')]
        for text, val in sort_options:
            ttk.Radiobutton(options_frame, text=text, variable=self.sort_var, value=val).pack(side=tk.LEFT, padx=5)

        self.search_button = ttk.Button(options_frame, text="开始搜索", command=self.start_new_search)
        self.search_button.pack(side=tk.RIGHT, padx=5)

    def create_results_view(self, parent):
        self.tree = ttk.Treeview(parent, columns=("name", "size", "date", "peers", "magnet"), show="headings")
        self.tree.heading("name", text="名称")
        self.tree.heading("size", text="大小")
        self.tree.heading("date", text="日期")
        self.tree.heading("peers", text="热度")
        self.tree.heading("magnet", text="磁力链接")
        self.tree.column("name", width=600, anchor=tk.W)
        self.tree.column("size", width=120, anchor=tk.CENTER)
        self.tree.column("date", width=150, anchor=tk.CENTER)
        self.tree.column("peers", width=80, anchor=tk.CENTER)
        self.tree.column("magnet", width=400, anchor=tk.W)

        vsb = ttk.Scrollbar(parent, orient="vertical", command=self.tree.yview)
        hsb = ttk.Scrollbar(parent, orient="horizontal", command=self.tree.xview)
        self.tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)
        self.tree.grid(row=0, column=0, sticky="nsew")
        vsb.grid(row=0, column=1, sticky="ns")
        hsb.grid(row=1, column=0, sticky="ew")

    def create_action_buttons(self, parent):
        buttons_frame = ttk.Frame(parent)
        buttons_frame.grid(row=0, column=0, sticky="w", padx=5)
        self.copy_button = ttk.Button(buttons_frame, text="复制磁力链接", command=self.copy_magnet_link)
        self.copy_button.pack(side=tk.LEFT, padx=(0, 5))
        self.export_button = ttk.Button(buttons_frame, text="导出为CSV", command=self.export_to_csv)
        self.export_button.pack(side=tk.LEFT)

    def create_pagination_controls(self, parent):
        pagination_frame = ttk.Frame(parent)
        pagination_frame.grid(row=0, column=1, sticky="e")
        self.prev_button = ttk.Button(pagination_frame, text="<< 上一页", command=self.prev_page)
        self.prev_button.pack(side=tk.LEFT, padx=5)

        self.page_info_var = tk.StringVar(value="第 1 / 1 页")
        ttk.Label(pagination_frame, textvariable=self.page_info_var).pack(side=tk.LEFT, padx=5)

        self.next_button = ttk.Button(pagination_frame, text="下一页 >>", command=self.next_page)
        self.next_button.pack(side=tk.LEFT, padx=5)

        ttk.Label(pagination_frame, text="跳转至:").pack(side=tk.LEFT, padx=(10, 5))
        self.page_jump_var = tk.StringVar()
        self.page_jump_entry = ttk.Entry(pagination_frame, textvariable=self.page_jump_var, width=5)
        self.page_jump_entry.pack(side=tk.LEFT)
        self.page_jump_button = ttk.Button(pagination_frame, text="跳转", command=self.jump_to_page)
        self.page_jump_button.pack(side=tk.LEFT, padx=5)
        
        self.total_results_var = tk.StringVar()
        ttk.Label(pagination_frame, textvariable=self.total_results_var).pack(side=tk.LEFT, padx=10)

    def start_new_search(self):
        self.current_page = 1
        keywords = []
        custom_kw = self.keyword_var.get().strip()
        if custom_kw:
            keywords.append(custom_kw)
        for kw, var in self.preset_vars.items():
            if var.get():
                keywords.append(f'"{kw}"')
        ext_keywords = [ext for ext, var in self.ext_vars.items() if var.get()]
        if ext_keywords:
            keywords.append(f'({" OR ".join(ext_keywords)})')
        
        if not keywords:
            messagebox.showwarning("提示", "请输入或选择一个搜索关键词。")
            return
        
        self.last_search_keywords = keywords
        self.execute_search()

    def execute_search(self):
        self.toggle_controls(tk.DISABLED)
        self.status_var.set(f"正在从 {self.current_rule.get()} 的第 {self.current_page} 页搜索...")
        self.tree.delete(*self.tree.get_children())
        
        search_thread = threading.Thread(target=self.search_worker)
        search_thread.daemon = True
        search_thread.start()

    def search_worker(self):
        try:
            rule_name = self.current_rule.get()
            selected_rule = next((r for r in self.rules if r['name'] == rule_name), None)
            if not selected_rule:
                raise ValueError(f"规则 '{rule_name}' 未找到!")

            sort_by = self.sort_var.get()
            
            data = fetch_torrents(
                query=self.last_search_keywords, 
                sort_by_key=sort_by, 
                page=self.current_page,
                rule=selected_rule
            )
            self.root.after(0, self.update_ui_with_results, data)
        except Exception as e:
            self.root.after(0, self.update_status, f"发生错误: {e}")
            self.root.after(0, self.toggle_controls, tk.NORMAL)

    def update_ui_with_results(self, data):
        results = data.get("magnets", [])
        stats = data.get("stats", {})
        
        self.total_pages = int(str(stats.get("total_pages", "1")).replace(',', ''))
        total_results = stats.get("total_results", "0")

        self.page_info_var.set(f"第 {self.current_page} / {self.total_pages} 页")
        self.total_results_var.set(f"(共约 {total_results} 条结果)")

        if not results:
            self.status_var.set("当前页未找到任何结果。")
        else:
            for item in results:
                self.tree.insert("", tk.END, values=(
                    item.get("magnet_name", "N/A"), item.get("magnet_size", "N/A"),
                    item.get("magnet_date", "N/A"), item.get("magnet_rank", "N/A"),
                    item.get("magnet", "N/A")
                ))
            self.status_var.set(f"搜索完成，在第 {self.current_page} 页找到 {len(results)} 条结果。")
        
        self.toggle_controls(tk.NORMAL)
        self.update_pagination_buttons()

    def prev_page(self):
        if self.current_page > 1:
            self.current_page -= 1
            self.execute_search()

    def next_page(self):
        if self.current_page < self.total_pages:
            self.current_page += 1
            self.execute_search()

    def jump_to_page(self):
        try:
            page = int(self.page_jump_var.get())
            if 1 <= page <= self.total_pages:
                self.current_page = page
                self.execute_search()
            else:
                messagebox.showerror("错误", f"请输入一个介于 1 和 {self.total_pages} 之间的页码。")
        except ValueError:
            messagebox.showerror("错误", "请输入一个有效的页码。")

    def copy_magnet_link(self):
        selected_item = self.tree.focus()
        if not selected_item:
            messagebox.showinfo("提示", "请先在表格中选择一个条目。")
            return
        item_values = self.tree.item(selected_item, "values")
        magnet_link = item_values[4]
        self.root.clipboard_clear()
        self.root.clipboard_append(magnet_link)
        self.status_var.set(f"已复制磁力链接: {magnet_link[:70]}...")

    def export_to_csv(self):
        if not self.tree.get_children():
            messagebox.showinfo("提示", "当前没有可导出的结果。")
            return
        
        filepath = filedialog.asksaveasfilename(
            defaultextension=".csv",
            filetypes=[("CSV 文件", "*.csv"), ("所有文件", "*.*")],
            title="导出为CSV文件"
        )
        if not filepath:
            return

        try:
            with open(filepath, 'w', newline='', encoding='utf-8-sig') as f:
                writer = csv.writer(f)
                writer.writerow(['名称', '大小', '日期', '热度', '磁力链接'])
                for row_id in self.tree.get_children():
                    writer.writerow(self.tree.item(row_id)['values'])
            self.status_var.set(f"结果已成功导出到 {filepath}")
            messagebox.showinfo("成功", "数据已成功导出！")
        except Exception as e:
            messagebox.showerror("导出失败", f"导出过程中发生错误: {e}")
            self.status_var.set(f"导出失败: {e}")

    def toggle_controls(self, state):
        for widget in [self.search_button, self.copy_button, self.export_button]:
            widget.config(state=state)
        self.update_pagination_buttons()

    def update_pagination_buttons(self):
        state = self.search_button.cget('state')
        if state == tk.DISABLED:
            self.prev_button.config(state=tk.DISABLED)
            self.next_button.config(state=tk.DISABLED)
            self.page_jump_button.config(state=tk.DISABLED)
        else:
            self.prev_button.config(state=tk.NORMAL if self.current_page > 1 else tk.DISABLED)
            self.next_button.config(state=tk.NORMAL if self.current_page < self.total_pages else tk.DISABLED)
            self.page_jump_button.config(state=tk.NORMAL)

    def update_status(self, message):
        self.status_var.set(message)

if __name__ == "__main__":
    root = tk.Tk()
    app = TorrentSearchApp(root)
    root.mainloop()
